package com.jh.paymentchannel.service;

import cn.jh.common.core.base.Joiners;
import cn.jh.common.utils.CommonConstants;
import cn.jh.common.utils.CommonsUtil;
import cn.jh.common.utils.QRCodeUtil;
import cn.jh.common.utils.TokenUtil;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.TypeReference;
import com.alipay.api.AlipayApiException;
import com.google.common.base.Strings;
import com.jh.paymentchannel.payment.alipay.AlipayConfig;
import com.jh.paymentchannel.pojo.AlipayAuthToken;
import com.jh.paymentchannel.pojo.AlipayAuthTokenVO;
import com.jh.paymentchannel.pojo.WeixinServiceNo;
import com.jh.paymentchannel.util.Util;
import com.jh.paymentchannel.util.jifu.CommonUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Controller;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.web.bind.annotation.PathVariable;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.net.URI;
import java.util.Map;
import java.util.Objects;

import static cn.jh.common.tools.Strings.isNullOrEmpty;
import static org.springframework.web.bind.annotation.RequestMethod.GET;
import static org.springframework.web.bind.annotation.RequestMethod.POST;

/**
 * 保存支付配置信息
 */
@Controller
public class ConfigureService {

    private Logger log = LoggerFactory.getLogger(ConfigureService.class);

    private final PassagewayConfigureService passagewayConfigureService;
    private final Util util;
    private final AlipayConfig alipayConfig;

    @Autowired
    public ConfigureService(PassagewayConfigureService passagewayConfigureService,
                            Util util, AlipayConfig alipayConfig) {
        this.passagewayConfigureService = passagewayConfigureService;
        this.util = util;
        this.alipayConfig = alipayConfig;
    }

    @Value("${platform.uploadpath}")
    private String uploadpath;
    @Value("${platform.outPutPath}")
    private String outPutPath;

    /**
     * 保存微信配置信息
     * @param entity
     * @return
     */
    @RequestMapping(method = POST, value = "/v1.0/paymentchannel/weixin/configure/{token}")
    public @ResponseBody Object weixinConfigure(WeixinServiceNo entity,@PathVariable("token")String token) {
        try {
            TokenUtil.getUserId(token);
        } catch (Exception e) {
            return CommonsUtil.returnError("登录token已过期");
        }
        try {
            entity = passagewayConfigureService.saveWeixinServiceNo(entity);

            if (Strings.isNullOrEmpty(entity.getAppid())) {
                entity.setAppid(entity.getPartner());
            }
            Map<String, Object> result = associatePayConfigure(entity.getShopId(), null, entity.getAppid());
            String respCode = (String) result.get(CommonConstants.RESP_CODE);
            if (!Objects.equals(respCode, CommonConstants.SUCCESS)) {
                return CommonsUtil.returnError((String) result.get(CommonConstants.RESP_MESSAGE));
            }
            return CommonsUtil.returnOK();
        } catch (Exception e){
            log.error("PassagewayConfigureController.saveWeixinShopConfigure, 保存微信配置信息异常=" + e);
            if (e.getMessage().contains("微信子商户号已存在")) {
                return CommonsUtil.returnError(e.getMessage());
            }
            return CommonsUtil.returnError("保存微信配置信息失败！");
        }
    }

    /**
     * 查询支付宝配置信息
     */
    @RequestMapping(method = POST, value = "/v1.0/paymentchannel/alipay/query/{token}")
    public @ResponseBody Object findAlipayConfigure(HttpServletRequest request, @PathVariable("token")String token) {
        try {
            TokenUtil.getUserId(token);
        } catch (Exception e) {
            return CommonsUtil.returnError("登录token已过期");
        }
        String shopId = request.getParameter("shopId");
        if (Strings.isNullOrEmpty(shopId)) {
            return CommonsUtil.returnError("缺少必要参数");
        }
        boolean isCode = Boolean.valueOf(request.getParameter("isCode"));
        AlipayAuthToken authToken = passagewayConfigureService.findAlipayAuthToken(shopId);
        try {
            if (authToken == null || authToken.needRefreshQrcCode()) { // 需要生成二维码
                String authUrl = alipayConfig.pieceAppToAuthUrl(shopId), imageName = "auth_"+shopId+".jpg";
                String outUrl = Joiners.empty().join(outPutPath, imageName);
                QRCodeUtil.qrCode(authUrl, outUrl);
                if (authToken == null) {
                    authToken = AlipayAuthToken.newToken(shopId);
                }
                authToken.updateQrcCode(imageName);
                passagewayConfigureService.updateAuthToken(authToken);
            }
            return CommonsUtil.returnOK(isCode ? AlipayAuthTokenVO.onlyCode(authToken, uploadpath) :
                    AlipayAuthTokenVO.transform(shopId, alipayConfig, authToken, uploadpath));
        } catch (Exception ex) {
            ex.printStackTrace();
            return CommonsUtil.returnError("数据异常");
        }
    }

    /**
     * 商户授权回调业务处理
     */
    @RequestMapping(value = "/v1.0/paymentchannel/alipay/auth_callback", method = POST)
    public @ResponseBody Object appAuthCallback(HttpServletRequest request) {
        String shopId = request.getParameter("shop_id");
        String appId = request.getParameter("app_id");
        String appAuthCode = request.getParameter("app_auth_code");
        if (isNullOrEmpty(shopId) || isNullOrEmpty(appId) || isNullOrEmpty(appAuthCode)) {
            return CommonsUtil.returnError("缺少必要参数");
        }
        try {
            AlipayAuthToken authToken = passagewayConfigureService.alipayOpenAuthToken(shopId, appId, appAuthCode);
            if (authToken == null) {
                return CommonsUtil.returnError("支付宝授权失败");
            }
            // 更新商户注册信息中的支付宝关联信息
            Map<String, Object> result = associatePayConfigure(shopId, authToken.getAppId(), null);
            String respCode = (String) result.get(CommonConstants.RESP_CODE);
            String message;
            if (Objects.equals(respCode, CommonConstants.SUCCESS)) {
                message = "支付宝授权并关联商户成功";
            } else {
                String respMsg = (String) result.get(CommonConstants.RESP_MESSAGE);
                message = "支付宝授权成功，但商户关联失败(" + respMsg +")";
            }
            return CommonsUtil.returnSuccess(message, authToken);
        } catch (AlipayApiException e) {
            e.printStackTrace();
            return CommonsUtil.returnError(e.getMessage());
        }
    }

    /**
     * 商户关联支付配置信息
     */
    private Map<String, Object> associatePayConfigure(String shopId, String alipayAppId, String wechatAppId) {
        RestTemplate restTemplate = new RestTemplate();
        URI uri = util.getServiceUrl("user", "error url request!");
        String url = uri.toString() + "/v1.0/user/shop/associate";
        MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
        if(!Strings.isNullOrEmpty(alipayAppId)){
            requestEntity.add("alipayAppId", alipayAppId);
        }
        if(!Strings.isNullOrEmpty(wechatAppId)){
            requestEntity.add("wechatAppId", wechatAppId);
        }
        //requestEntity.add("mobilePhone", mobilePhone);
        String result = restTemplate.postForObject(url, requestEntity, String.class);
        return JSON.parseObject(result, new TypeReference<Map<String, Object>>(){});
    }

    /**
     * 配置同步补充接口
     */
    @RequestMapping(method = POST, value = "/v1.0/paymentchannel/{channel}/supply/{token}")
    public @ResponseBody
    Object supplyAlipayConfig(@PathVariable("channel") String channel, @PathVariable("token") String token, HttpServletRequest request) {
        try {
            TokenUtil.getUserId(token);
        } catch (Exception e) {
            return CommonsUtil.returnError("登录token已过期");
        }
        String shopId = request.getParameter("shopId");
        if (Strings.isNullOrEmpty(shopId)) {
            return CommonsUtil.returnError("商户id不能为空");
        }
        AlipayAuthToken authToken = null;
        WeixinServiceNo weixinConfig = null;
        if (channel.equalsIgnoreCase("alipay")) {
            authToken = passagewayConfigureService.findAlipayAuthToken(shopId);
            if (authToken == null) {
                return CommonsUtil.returnError("支付宝授权信息不存在");
            }
            if (!authToken.isEnabled()) {
                return CommonsUtil.returnError("支付宝商户授权未完成或无效");
            }
        } else if (channel.equalsIgnoreCase("wechat")) {
            weixinConfig = passagewayConfigureService.findWeixinServiceNo(shopId);
            if (weixinConfig == null) {
                return CommonsUtil.returnError("微信配置信息不存在");
            }
            if (isNullOrEmpty(weixinConfig.getPartner())) {
                return CommonsUtil.returnError("微信配置无效");
            }
        } else {
            return CommonsUtil.returnError("未知请求，请检查接口");
        }

        try {
            RestTemplate restTemplate = new RestTemplate();
            URI uri = util.getServiceUrl("user", "error url request!");
            String url = uri.toString() + "/v1.0/user/shop/supply_config";
            MultiValueMap<String, String> requestEntity = new LinkedMultiValueMap<>();
            if (authToken != null) {
                requestEntity.add("alipayAppId", authToken.getAppId());
            }
            if (weixinConfig != null) {
                requestEntity.add("wechatAppId", weixinConfig.getPartner());
            }
            requestEntity.add("shopId", shopId);
            String result = restTemplate.postForObject(url, requestEntity, String.class);
            Map<String, Object> response = JSON.parseObject(result, new TypeReference<Map<String, Object>>() {
            });
            String respCode = (String) response.get(CommonConstants.RESP_CODE);
            if (!Objects.equals(respCode, CommonConstants.SUCCESS)) {
                return CommonsUtil.returnError((String) response.get(CommonConstants.RESP_MESSAGE));
            }
            return CommonsUtil.returnSuccess("配置绑定成功");
        } catch (Exception ex) {
            return CommonsUtil.returnError("User服务请求异常");
        }
    }

    /**
     * 查询微信配置信息
     * @param entity
     * @return
     */
    @RequestMapping(method = GET, value = "/v1.0/paymentchannel/weixin/query")
    public @ResponseBody
    Object weixinQuery(WeixinServiceNo entity) {
        try {
            return CommonUtil.returnSuccess(passagewayConfigureService.queryWeixinServiceNo(entity));
        }catch (Exception e){
            log.error("PassagewayConfigureController.queryWeixinServiceNo,查询微信配置信息异常=" + e);
            return CommonUtil.returnError("查询微信配置信息失败!");
        }
    }

    /**
     * 查询商户指定渠道的支付配置信息
     */
    @RequestMapping(method = GET, value = "/v1.0/paymentchannel/query/channel")
    public @ResponseBody
    Object queryPayChannel(@RequestParam("shopId") String shopId, @RequestParam("channel") String channel) {
        if (channel.equalsIgnoreCase("alipay")) {
            AlipayAuthToken authToken = passagewayConfigureService.findAlipayAuthToken(shopId);
            if (authToken == null) {
                return CommonsUtil.returnError("支付宝配置信息不存在");
            }
            return CommonsUtil.returnOK(authToken);
        } else {
            WeixinServiceNo weixinServiceNo = passagewayConfigureService.findWeixinServiceNo(shopId);
            if (weixinServiceNo == null) {
                return CommonsUtil.returnError("微信配置信息不存在");
            }
            return CommonsUtil.returnOK(weixinServiceNo);
        }
    }
}